/*
 * FeedRepresentation.java
 *
 * Created on March 27, 2007, 11:55 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.atomojo.app;

import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import org.atomojo.app.auth.User;
import org.atomojo.app.db.Entry;
import org.atomojo.app.db.Feed;
import org.infoset.xml.Document;
import org.infoset.xml.DocumentLoader;
import org.infoset.xml.XMLException;
import org.infoset.xml.sax.SAXDocumentLoader;
import org.restlet.Application;
import org.restlet.data.CharacterSet;
import org.restlet.data.MediaType;
import org.restlet.data.Parameter;
import org.restlet.data.Status;
import org.restlet.data.Tag;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;

/**
 *
 * @author alex
 */
public class EntryResource extends AtomResource {

   static List<Parameter> entryParameters = Collections.singletonList(new Parameter("type","entry"));

   App app;
   Entry entry;
   UUID entryId;
   
   /** Creates a new instance of FeedRepresentation */
   public EntryResource(Application app,Feed feed,Entry entry,Storage storage) {
      super(app,feed,storage);
      this.entry = entry;
      this.entryId = entry.getUUID();
      this.app = new App(app.getContext().getLogger(),feed.getDB(),storage,app.getMetadataService());
   }
   
   
   public UUID getEntryId() {
      return entryId;
   }

   public Representation get() {
      try {
         String feedBaseURI = getRequest().getResourceRef().getParentRef().getParentRef().toString();
         Representation rep = app.getEntryRepresentation(feedBaseURI,feed,entryId);
         if (rep==null) {
            getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
            return null;
         } else {
            rep.setTag(new Tag(Long.toString(entry.getEdited().getTime()),false));
            // Don't trust the storage to get the modification right
            rep.setModificationDate(entry.getEdited());
         }
         MediaType entryType = new MediaType(rep.getMediaType().getName(),rep.getMediaType().getParameters().createSeries(entryParameters));
         rep.setMediaType(entryType);
         getResponse().setStatus(Status.SUCCESS_OK);
         return rep;
      } catch (AppException ex) {
         getResponse().setStatus(ex.getStatus());
         return new StringRepresentation(ex.getMessage());
      }
   }
   
   public Representation put(Representation entity) {
      if (!entity.getMediaType().getName().equals(MediaType.APPLICATION_ATOM.getName())) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("Cannot put to an entry using media type "+entity.getMediaType());
      }
      User user = (User)getRequest().getAttributes().get(App.USER_ATTR);
      String charset = entity.getMediaType().getParameters().getValues("charset");
      if (charset==null) {
         charset = "UTF-8";
      }
      try {
         DocumentLoader loader = new SAXDocumentLoader();
         Reader r = new InputStreamReader(entity.getStream(),charset);
         Document doc = loader.load(r);
         r.close();
         
         // Find the entry
         
         try {
            Entry entry = app.updateEntry(user,feed,entryId,doc);
            getResponse().setStatus(Status.SUCCESS_OK);
            String feedBaseURI = getRequest().getResourceRef().getParentRef().getParentRef().toString();
            Representation rep = app.getEntryRepresentation(feedBaseURI,entry);
            rep.setCharacterSet(CharacterSet.UTF_8);
            return rep;
         } catch (AppException ex) {
            if (ex.getStatus()==Status.SERVER_ERROR_INTERNAL) {
               getContext().getLogger().log(Level.SEVERE,ex.getMessage(),ex.getCause());
            }
            getResponse().setStatus(ex.getStatus());
            return new StringRepresentation(ex.getMessage());
         }
         
      } catch (XMLException ex) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("Cannot parse content: "+ex.getMessage());
      } catch (Exception ex) {
         getContext().getLogger().log(Level.SEVERE,"Fatal exception during post:"+ex.getMessage(),ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Fatal error "+ex.getMessage());
      }
      
   }
   
   public Representation delete()
   {
      try {
         
         Entry entry = feed.findEntry(entryId);
         if (entry==null) {
            getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
            return null;
         }
         try {
            app.deleteEntry(feed,entry);
            getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
            return null;
         } catch (AppException ex) {
            if (ex.getStatus()==Status.SERVER_ERROR_INTERNAL) {
               getContext().getLogger().log(Level.SEVERE,ex.getMessage(),ex.getCause());
            }
            getResponse().setStatus(ex.getStatus());
            return new StringRepresentation(ex.getMessage());
         }
      } catch (Exception ex) {
         getContext().getLogger().log(Level.SEVERE,"Exception while deleting entry: "+ex.getMessage(),ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Exception while deleting entry.");
      }
   }
   
   public Representation head() {
      try {
         final Entry entry = feed.findEntry(entryId);
         getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
         Representation rep = new StringRepresentation("",MediaType.APPLICATION_ATOM);
         rep.setModificationDate(entry.getEdited());
         rep.setTag(new Tag(Long.toString(entry.getEdited().getTime()),false));
         return rep;
      } catch (SQLException ex) {
         getContext().getLogger().log(Level.SEVERE,"Exception while deleting entry: "+ex.getMessage(),ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Exception while deleting entry.");
      }
   }
}
